<?php

declare(strict_types=1);

namespace App\Traits\Model\App;


use App\Model\App\AppAllow as AppAllowModel;
use App\Exception\InvalidRequestException;
use App\Model\Shop\Shop;
use Hyperf\Database\Model\Relations\BelongsTo;
use Hyperf\Database\Model\Relations\HasMany;
use function Hyperf\Translation\__;

trait App
{

    /**
     * 关联店铺
     * @return BelongsTo
     */
    public function shop():BelongsTo
    {
        return $this->belongsTo(Shop::class);
    }

    /**
     * 关联白名单
     * @return HasMany
     */
    public function allow():HasMany
    {
        return $this->hasMany(AppAllowModel::class);
    }

    /**
     * 验签
     * @param array $params
     * @return bool
     */
    public function validate(array $params)
    {
        if ($this->allow()->exists()) {
            if (!$this->allow()->where('ip', ip2long(getIp()))->exists()) {
                throw new InvalidRequestException(__('message.ip.allow', [
                    'ip' => getIp()
                ]));
            }
        }

        $sign = $this->encry($params);
        logs($sign);
        return $sign === $params['sign'];
    }

    /**
     * 获取加密参数
     * @param array $params
     * @return string
     */
    public function encry(array $params)
    {
        $params = $this->sort($params);
        $splic = $this->splic($params);
        logs($splic);
        return md5($splic);
    }

    /**
     * 参数拼接
     * @param array $params
     * @return string
     */
    protected function splic(array $params):string
    {
        $strArr = [];
        foreach ($params as $key => $param) {
            if ($key === 'sign' || null === $param) {
                continue;
            }
            $value = is_array($param)?str_replace('"', '', json_encode($param, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)):$param;
            $strArr[] = $key.'='.(is_string($value)?htmlspecialchars_decode($value):$value);
        }
        $str = implode('&', $strArr);
        return $this->app_secret.$str.$this->app_secret;
    }

    /**
     * 排序
     * @param array $params
     */
    protected function sort(array $params)
    {
        ksort($params);
        foreach ($params as &$param) {
            if (is_array($param)) {
                $param = $this->sort($param);
            }
        }

        return $params;
    }
}
